除了物件,JavaScript 中還有陣列,也是非常重要的型別,
陣列可以儲存任何資料格式,像是 number
、string
、boolean
、object
或是混合資料。
TypeScript 也支援任何 JavaScript 陣列,該陣列的型別可以很靈活也可以很嚴謹。
const person: {
name: string;
age: number;
hobbies: string[];
} = {
name: '肉鬆',
age: 30,
hobbies: ['Sport', 'Cooking'],
};
string[]
:中括號前面是儲存在陣列中的資料型別,即便沒有給 hobbies: string[]
明確的型別,
TypeScript 也會透過陣列只有字串自動推斷 hobbies
應該會是一個字串陣列。
在 TypeScript 中,數字陣列和字串陣列基本概念相似,只是陣列中資料型別不同。
const numbers: number[] = [1, -5, 0.5, NaN];
讓我們透過一個簡單的範例演示陣列型別的錯誤:
let colors: string[];
colors = 'green'; // 報錯 - 第一個錯誤
colors = ['red', 'blue', 1]; // 報錯 - 第二個錯誤
程式碼中,我們宣告了一個名為 colors
變數,並假設它是一個空的字串陣列,
重要的是,我們告訴 TypeScript 要儲存的不僅僅是一個字串(string
),而是一個字串陣列(string[]
)。
從程式碼中可以看到有兩個錯誤:
第一個錯誤:當我們將 colors
賦值為字串 green
,導致錯誤。這是因為我們定義 colors
是一個字串陣列,而不僅僅是單一字串。
第二個錯誤:由於我們已將 colors
定義為字串陣列,因此將一個 number
型別的值加到字串陣列中會導致錯誤。
讓我們改寫程式碼,解決第二個錯誤:
let colors: any[];
colors = ['red', 'blue', 1];
解決這個問題的一種方法是使用 TypeScript 的特殊型別關鍵字 any
, any
型別在 TypeScript 中具有特殊涵義,允許包含任何型別的資料。這邊我們暫時不深入討論 any
,後續會詳細介紹。
接著我們看一個新的範例:
const person: {
name: string;
age: number;
hobbies: string[];
} = {
name: '肉鬆',
age: 30,
hobbies: ['Sport', 'Cooking'],
};
person.hobbies.forEach((hobby) => {
console.log(hobby); // Sport、Cooking
console.log(hobby.toUpperCase()); // SPORT、COOKING
console.log(hobby.map()); // 報錯
});
程式碼中,在 person
物件的 hobbies
屬性使用 forEach
,並且可以看到出現了錯誤訊息,為什麼呢?
首先,person
物件下的 hobbies
屬性被定義為字串陣列,因此對這個陣列進行迴圈時, hobby
的每個值都被認定為字串,這也意味著我們可以對 hobby
的值進行任何適用於字串的操作,像是範例中使用的 toUpperCase()
方法。
錯誤的部分是因為我們嘗試在 hobby
上使用 map
方法,map
方法用於陣列,而不適用於字串。
any
解決,但這種方式不太建議,因為會失去 TypeScript 強型別的優勢。